package com.gzhryc.pay.adaptation.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundAuthOperationDetailQueryModel;
import com.alipay.api.domain.AlipayFundAuthOrderAppFreezeModel;
import com.alipay.api.domain.AlipayFundAuthOrderUnfreezeModel;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.config.PropertyTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.pay.models.IPayOrder;
import com.gzhryc.pay.models.PreAuthCloseParam;
import com.gzhryc.pay.models.RentBillParam;
import com.gzhryc.pay.models.RevertBillParam;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class AlipayAdvancePayService implements Serializable {

    private static final long serialVersionUID = 1L;

	static Logger log = Logger.getLogger(AlipayAdvancePayService.class);

    DefaultAlipayConfig config;

    public AlipayAdvancePayService(){}

    public AlipayAdvancePayService(Properties properties) {
        this.config = PropertyTools.build(properties).getObject(DefaultAlipayConfig.class);
    }

    public AlipayAdvancePayService(DefaultAlipayConfig config) {
        this.config = config;
    }

    public AlipayFundAuthOrderAppFreezeResponse applyCreateOrder(IPayOrder preAuthOrder, RentBillParam param) {
        AlipayFundAuthOrderAppFreezeResponse response = null;
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest();
            AlipayFundAuthOrderAppFreezeModel model = new AlipayFundAuthOrderAppFreezeModel();
            model.setOrderTitle(preAuthOrder.getTitle());
            model.setOutOrderNo(preAuthOrder.getTradeNo());
            model.setOutRequestNo(preAuthOrder.getTradeNo());
            model.setPayeeUserId(config.getPid());
            model.setPayTimeout(param.getValidDay() + "d");
            model.setProductCode("PRE_AUTH_ONLINE");
            model.setAmount(NumberTools.getMoneyStr(preAuthOrder.getPayMoney()));
            // 需要支持信用授权，该字段必传
            model.setExtraParam("{\"category\":\"" + this.config.getCategory() + "\",\"outStoreCode\":\"" + param.getDeviceSn() + "\",\"serviceId\":\""
                    + this.config.getServiceId() + "\",\"outStoreAlias\":\"" + param.getRentAddress() + "\"}");
            request.setBizModel(model);
            request.setNotifyUrl(this.config.getPreAuthNotifyUrl());

            // 注意这里是sdkExecute，可以获取签名参数
            response = httpClient.sdkExecute(request);
            return response;
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public AlipayTradePayResponse applyFinishOrder(IPayOrder preAuthOrder, RevertBillParam param) {
        AlipayTradePayResponse response = null;
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayTradePayRequest request = new AlipayTradePayRequest();
            AlipayTradePayModel model = new AlipayTradePayModel();
            model.setOutTradeNo(preAuthOrder.getTradeNo());
            model.setProductCode("PRE_AUTH_ONLINE");
            model.setAuthNo(preAuthOrder.getExternalTradeNo()); // 填写预授权冻结交易号
            model.setSubject(preAuthOrder.getTitle()); // 解冻转支付标题，用于展示在支付宝账单中
            model.setTotalAmount(NumberTools.getMoneyStr(param.getPayMoney()));
            model.setSellerId(this.config.getPid());
            model.setBuyerId(preAuthOrder.getPayerId()); // 填写预授权用户uid，通过预授权冻结接口返回的payer_user_id字段获取
            model.setStoreId(param.getDeviceSn()); // 填写实际交易发生的终端编号，与预授权的outStoreCode保持一致即可
            model.setBody(preAuthOrder.getNote());
            model.setAuthConfirmMode("COMPLETE"); // 必须使用COMPLETE,传入该值用户剩余金额会自动解冻
            request.setBizModel(model);
            request.setNotifyUrl(this.config.getPreAuthPayNotifyUrl());

            if (StringUtils.isNotBlank(config.getCertificatePath())) {
                response = httpClient.certificateExecute(request);
            } else {
                response = httpClient.execute(request);
            }
            return response;
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public AlipayTradePayResponse applyPayOrder(IPayOrder preAuthOrder, IPayOrder payOrder) {
        AlipayTradePayResponse response = null;
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayTradePayRequest request = new AlipayTradePayRequest();
            AlipayTradePayModel model = new AlipayTradePayModel();
            model.setOutTradeNo(payOrder.getTradeNo()); // 预授权转支付商户订单号，为新的商户交易流水号；如果重试发起扣款，商户订单号不要变；
            model.setProductCode("PRE_AUTH_ONLINE");
            model.setAuthNo(preAuthOrder.getExternalTradeNo()); // 填写预授权冻结交易号
            model.setSubject(payOrder.getTitle());
            model.setTotalAmount(NumberTools.getMoneyStr(payOrder.getPayMoney())); // 结算支付金额
            model.setSellerId(this.config.getPid());
            model.setBuyerId(payOrder.getPayerId()); // 填写预授权用户uid，通过预授权冻结接口返回的payer_user_id字段获取
            model.setBody(payOrder.getNote());
            model.setAuthConfirmMode("COMPLETE"); // 必须使用COMPLETE,传入该值用户剩余金额会自动解冻
            request.setBizModel(model);
            request.setNotifyUrl(this.config.getPreAuthPayNotifyUrl());

            if (StringUtils.isNotBlank(config.getCertificatePath())) {
                response = httpClient.certificateExecute(request);
            } else {
                response = httpClient.execute(request);
            }
            return response;
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public AlipayFundAuthOperationDetailQueryResponse queryByTradeNo(String tradeNo,String requestNo) {
        AlipayFundAuthOperationDetailQueryResponse response = null;
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayFundAuthOperationDetailQueryRequest request = new AlipayFundAuthOperationDetailQueryRequest();
            AlipayFundAuthOperationDetailQueryModel model = new AlipayFundAuthOperationDetailQueryModel();
            model.setOutOrderNo(tradeNo); // 商户的授权资金订单号，与支付宝的授权资金订单号不能同时为空
            model.setOutRequestNo(requestNo); // 商户的授权资金操作流水号，与支付宝的授权资金操作流水号不能同时为空，该值为冻结或解冻是的outRequestNo
            request.setBizModel(model);

            if (StringUtils.isNotBlank(config.getCertificatePath())) {
                response = httpClient.certificateExecute(request);
            } else {
                response = httpClient.execute(request);
            }
            return response;
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public AlipayFundAuthOperationDetailQueryResponse queryByExternalTradeNo(String externalTradeNo,String operationId){
        AlipayFundAuthOperationDetailQueryResponse response = null;
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayFundAuthOperationDetailQueryRequest request = new AlipayFundAuthOperationDetailQueryRequest();
            AlipayFundAuthOperationDetailQueryModel model = new AlipayFundAuthOperationDetailQueryModel();
            model.setAuthNo(externalTradeNo);
            model.setOperationId(operationId);
            request.setBizModel(model);

            if (StringUtils.isNotBlank(config.getCertificatePath())) {
                response = httpClient.certificateExecute(request);
            } else {
                response = httpClient.execute(request);
            }
            return response;
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public AlipayFundAuthOrderUnfreezeResponse applyUnfreeze(PreAuthCloseParam param) {
        AlipayFundAuthOrderUnfreezeResponse response = null;
        if (StringUtils.isBlank(param.getExternalTradeNo())) {
            return null;
        }
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest();
            AlipayFundAuthOrderUnfreezeModel model = new AlipayFundAuthOrderUnfreezeModel();
            model.setAuthNo(param.getExternalTradeNo()); // 支付宝资金授权订单号，在授权冻结成功时返回需要入库保存
            model.setOutRequestNo(param.getTradeNo()); // 同一商户每次不同的资金操作请求，商户请求流水号不能重复,且与冻结流水号不同
            model.setAmount(NumberTools.getMoneyStr(param.getDepositMoney())); // 本次操作解冻的金额，单位为：元（人民币），精确到小数点后两位
            model.setRemark(param.getReason()); // 商户对本次解冻操作的附言描述，长度不超过100个字母或50个汉字
            // 选填字段，信用授权订单，针对信用全免订单，传入该值完结信用订单，形成芝麻履约记录
            model.setExtraParam("{\"unfreezeBizInfo\":\"{\\\"bizComplete\\\":\\\""+param.getBizComplete()+"\\\"}\"}");
            request.setBizModel(model);

            if (StringUtils.isNotBlank(config.getCertificatePath())) {
                response = httpClient.certificateExecute(request);
            } else {
                response = httpClient.execute(request);
            }
            return response;
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 24小时内调用
     * @param param
     * @return
     */
    public AlipayFundAuthOperationCancelResponse applyCloseOrder(PreAuthCloseParam param) {
        AlipayFundAuthOperationCancelResponse response = null;
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayFundAuthOperationCancelRequest request = new AlipayFundAuthOperationCancelRequest();
            request.setBizContent("{" + "\"out_order_no\":\"" + param.getTradeNo() + "\"," + "\"out_request_no\":\"" + param.getRequestNo() + "\","
                    + "\"remark\":\"授权撤销\"" + "  }");

            if (StringUtils.isNotBlank(config.getCertificatePath())) {
                response = httpClient.certificateExecute(request);
            } else {
                response = httpClient.execute(request);
            }
            return response;
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public AlipayTradeOrderinfoSyncResponse syncOrderInfo(IPayOrder preAuthOrder,Map<String,Object> params){
        AlipayTradeOrderinfoSyncResponse response = null;
        try {
            DefaultAlipayClient httpClient = AliHttpClient.getHttpClient(config);

            AlipayTradeOrderinfoSyncRequest request = new AlipayTradeOrderinfoSyncRequest();
            String bizType= "CREDIT_AUTH";
            String status = "CLOSED";
            if(params != null){
                Object obj = params.get("bizType");
                if(obj != null){
                    bizType = obj.toString();
                }
                obj = params.get("status");
                if(obj != null){
                    status = obj.toString();
                }
            }

            Map<String,Object> bizContent = new HashMap<>();
            bizContent.put("trade_no",preAuthOrder.getExternalTradeNo());
            bizContent.put("out_request_no",preAuthOrder.getTradeNo());
            bizContent.put("biz_type",bizType);


            Map<String,Object> orderBizInfo = new HashMap<>();
            orderBizInfo.put("status",status);
            bizContent.put("order_biz_info",JsonTools.toJson(orderBizInfo));
            request.setBizContent(JsonTools.toJson(bizContent));

            response = httpClient.execute(request);
        } catch (AlipayApiException e) {
            log.error(e.getMessage(), e);
        }catch (LogicException e) {
            log.error(e.getMessage(), e);
        }
        return response;
    }

}
